/*
 *  linmigrate - base interface implementation
 *
 *  Copyright (C) 2011 by Volodymyr M. Shcherbyna <volodymyr@shcherbyna.com>
 *
 *      This file is part of linmigrate.
 *
 *  linmigrate is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  linmigrate is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with linmigrate.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "idistributionhandler.h"

/**   C'tor of the class

    * @return initialized object
*/
IDistributionHandler::IDistributionHandler(QTextStream & console) : m_console(console)
{
}

/**   Identifying the current distribution

    * @return type of distribution
*/
IDistribution IDistributionHandler::Identify()
{
    IDistribution retVal = Unknown;

    return retVal;
}

/**   Compressing any particular directory

    * @return boolean
*/
bool IDistributionHandler::CompressDirectory(QString & szPath)
{
    QProcess    tar;
    QStringList tarParams;

    tarParams << "--create";
    tarParams << "--file=export.tar";
    tarParams << szPath;

    tar.start("tar", tarParams);

    if (!tar.waitForFinished())
    {
        return false;
    }

    return (tar.exitCode() == 0);
}

/**   UnCompressing any particular directory

    * @return boolean
*/
bool IDistributionHandler::UnCompressDirectory(QString & szPath, QString & szWhere)
{
    QProcess    tar;
    QStringList tarParams;

    tarParams << "-C";
    tarParams << szWhere;
    tarParams << "-xf";
    tarParams << szPath;    

    tar.start("tar", tarParams);

    if (!tar.waitForFinished())
    {
        return false;
    }

    return (tar.exitCode() == 0);
}

/**   Cleaning any particular directory

    * @return boolean
*/
bool IDistributionHandler::CleanDirectory(const QString & szPath)
{
    QDir dir(szPath);
    bool result = true;

    if (dir.exists(szPath))
    {
        Q_FOREACH(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden  | QDir::AllDirs | QDir::Files, QDir::DirsFirst))
        {
            if (info.isDir())
            {
                result = CleanDirectory(info.absoluteFilePath());
            }
            else
            {
                result = QFile::remove(info.absoluteFilePath());
            }

            if (!result)
            {
                return result;
            }
        }

        result = dir.rmdir(szPath);
    }

    return result;
}

/**   Copying the /etc/hosts file

    * @return boolean
*/
bool IDistributionHandler::CopyHostsFile(const QString & szPath)
{
    return CopyFile("/etc/hosts", szPath + "/hosts");
}

/**   Copying the /etc/X11/xorg.conf file

    * @return boolean
*/
bool IDistributionHandler::CopyXorgFile(const QString & szPath)
{
    return CopyFile("/etc/X11/xorg.conf", szPath + "/xorg.conf");
}

/**   Copying the /etc/rc.local file

    * @return boolean
*/
bool IDistributionHandler::CopyRCLocalFile(const QString & szPath)
{
    return CopyFile("/etc/rc.local", szPath + "/rc.local");
}

/**   Copying the /etc/fstab file

    * @return boolean
*/
bool IDistributionHandler::CopyFstabFile(const QString & szPath)
{
    return CopyFile("/etc/fstab", szPath + "/fstab");
}

/**   Copying any particular file

    * @return boolean
*/
bool IDistributionHandler::CopyFile(const QString & szFrom, const QString & szTo)
{
    QProcess    cp;
    QStringList cpParams;

    cpParams << szFrom;
    cpParams << szTo;

    cp.start("cp", cpParams);

    if (!cp.waitForFinished())
    {
        return false;
    }

    return (cp.exitCode() == 0);
}

/**   Copying directory content

    * @return boolean
*/
bool IDistributionHandler::CopyDirectory(const QString & srcPath, const QString & dstPath, bool bExcludeSymlinks, QString & szExcludeDir)
{
    QDir parentDstDir(QFileInfo(dstPath).path());

    if (!parentDstDir.mkdir(QFileInfo(dstPath).fileName()))
    {
        return false;
    }

    QDir srcDir(srcPath);

    foreach(const QFileInfo & info, srcDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot))
    {
        QString srcItemPath = srcPath + "/" + info.fileName();
        QString dstItemPath = dstPath + "/" + info.fileName();

        if (info.isDir())
        {
            bool bCopyDir = true;

            if (bExcludeSymlinks == true)
            {
                bCopyDir = (info.isSymLink() == false);                
            }

            if (bCopyDir && srcItemPath != szExcludeDir)
            {
                if (!CopyDirectory(srcItemPath, dstItemPath, bExcludeSymlinks, szExcludeDir))
                {
                    return false;
                }
            }
        }
        else if (info.isFile())
        {
            if (!QFile::copy(srcItemPath, dstItemPath))
            {
                return false;
            }
            else
            {
                m_console << "Copying file: " << srcItemPath << endl;
            }
        }
        else
        {
            m_console << "Copying file: " << info.filePath() << " failed. Abort." << endl;

            return false;
        }
    }

    return true;
}

/**   Getting space information of particular directory

    * @return boolean
*/
bool IDistributionHandler::GetFreeDiskSpace(QString & szPath)
{
    struct stat     stst;
    struct statfs   stfs;

    if (::stat((const char*)szPath.data(), &stst) == -1)
    {
        return false;
    }

    if (::statfs((const char*)szPath.data(), &stfs) == -1)
    {
        return false;
    }

    unsigned long fFreeGBytes = (stfs.f_bavail * (stst.st_blksize)) / (1024 * 1024 * 1024);
    unsigned long fTotalBytes = (stfs.f_blocks * (stst.st_blksize)) / (1024 * 1024 * 1024);

    QString szPath2 = "/home/v/OS";

    GetFolderSize(szPath2);

    return true;
}

/**   Getting space information of particular directory

    * @return boolean
*/
bool IDistributionHandler::GetFolderSize(QString & path2)
{
    char  tmp[4096]  = {'\0'};
    char  cmd[128]   = {0x0};
    char  path[256]  = {0x0};
    long  total      = 0;
    FILE *in         = NULL;

    strcpy(path, "/home");
    sprintf(cmd,"ll %s | cut -c 35-45",path);
    in = popen(cmd, "r");

    if (in == NULL)
    {
        return false;
    }

    while(1)
    {
        if (fgets(tmp, 4095, in) != NULL)
        {
            total += atol(tmp);
        }
        else
        {
            if(feof(in))
            {
                break;
            }

            return false;
        }
    }

    pclose(in);

    /*if(errno)
    {
          perror("");
          exit(EXIT_FAILURE);
    }*/

    printf("Directory %s Total:%u\n",path, total);

    return true;
}
